import SafariServices
import SwiftUI
import WebKit

struct Webview: UIViewRepresentable {
    @Binding var dynamicHeight: CGFloat
    private var webview: WKWebView = .init()
    let html: String
    
    let lineHeight: CGFloat
    let imageRadius: CGFloat
    let fontType: fontType
    
    let colorScheme: colorScheme
    let colorImportant: Bool
    
    let linkOpenType: linkOpenType
    let linkColor: ColorSet
    
    let imageClick: ((Int, [String]) -> Void)?
    
    public init(dynamicHeight: Binding<CGFloat>, webview: WKWebView = WKWebView(), html: String, lineHeight: CGFloat, imageRadius: CGFloat, fontType: fontType, colorScheme: colorScheme, colorImportant: Bool, linkOpenType: linkOpenType, linkColor: ColorSet, imageClick: ((Int, [String]) -> Void)?) {
        self._dynamicHeight = dynamicHeight
        self.webview = webview
        
        self.html = html
        
        self.lineHeight = lineHeight
        self.imageRadius = imageRadius
        self.fontType = fontType
        
        self.colorScheme = colorScheme
        self.colorImportant = colorImportant
        
        self.linkOpenType = linkOpenType
        self.linkColor = linkColor
        
        self.imageClick = imageClick
    }
    
    public class Coordinator: NSObject, WKNavigationDelegate {
        var parent: Webview
        var imagesList: [String] = .init()

        init(_ parent: Webview) {
            self.parent = parent
        }
        
        public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            // 插入js代码
            webView.evaluateJavaScript("document.documentElement.scrollHeight", completionHandler: { height, _ in
                DispatchQueue.main.async {
                    self.parent.dynamicHeight = height as! CGFloat
                }
            })
            // 注入JS代码获取图片url和个数
            webView.evaluateJavaScript("""
                    function getImages(){\
                                    var imgs = document.getElementsByTagName('img');\
                                    var imgScr = '';\
                                    for(var i=0;i<imgs.length;i++){\
                                        if (i == 0){ \
                                           imgScr = imgs[i].src; \
                                        } else {\
                                           imgScr = imgScr +'***'+ imgs[i].src;\
                                        } \
                                    };\
                                    return imgScr;\
                                };
            """, completionHandler: nil)

            webView.evaluateJavaScript("getImages()") { [weak self] result, error in
                guard error == nil else {
                    return
                }

                guard let resultString: String = result as? String else {
                    return
                }

                // 分割字符串, 放入数组中
                for (_, num) in resultString.components(separatedBy: "***").enumerated() {
                    self?.imagesList.append(num)
                }

                print("一共有\(self?.imagesList.count ?? -1)张图片")
            }

            // 添加图片点击的回调
            webView.evaluateJavaScript("""
                        function registerImageClickAction(){\
                             var imgs = document.getElementsByTagName('img');\
                             for(var i=0;i<imgs.length;i++){\
                                 imgs[i].customIndex = i;\
                                 imgs[i].onclick=function(){\
                                    window.location.href='image-preview-index:'+this.customIndex;\
                                 }\
                             }\
                         }
            """, completionHandler: nil)

            webView.evaluateJavaScript("registerImageClickAction();", completionHandler: nil)
        }
        
        func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
            if navigationAction.navigationType == WKNavigationType.linkActivated {
                if let url = navigationAction.request.url {
                    let root = UIApplication.shared.windows.first?.rootViewController
                    switch parent.linkOpenType {
                    case .SFSafariView:
                        root?.present(SFSafariViewController(url: url), animated: true, completion: nil)
                    case .SFSafariViewWithReader:
                        let configuration = SFSafariViewController.Configuration()
                        configuration.entersReaderIfAvailable = true
                        root?.present(SFSafariViewController(url: url, configuration: configuration), animated: true, completion: nil)
                    case .Safari:
                        UIApplication.shared.open(url)
                    case .none:
                        print(url)
                    }
                }
                
                decisionHandler(WKNavigationActionPolicy.cancel)
                return
            }
            print("no link")
            decisionHandler(WKNavigationActionPolicy.allow)
            
            // 点击图片
            let url = navigationAction.request.url
            if url?.scheme == "image-preview-index" {
                // 图片点击回调
                let index = Int((url!.absoluteString as NSString).substring(from: "image-preview-index:".count)) ?? 0
                print("点击图片 INDEX = \(index)")
                print("点击图片 IMAGEPATH = " + url!.absoluteString)

                if index < imagesList.count {
                    parent.imageClick?(index, imagesList)
                }
                
//                decisionHandler(.cancel)
            }
//            else {
//                decisionHandler(.allow)
//            }
        }
    }
    
    public func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    public func makeUIView(context: Context) -> WKWebView {
        webview.scrollView.bounces = false
        webview.navigationDelegate = context.coordinator
        webview.scrollView.isScrollEnabled = false
        let htmlStart = """
        <HTML>
        <head>
            <meta name='viewport' content='width=device-width, shrink-to-fit=YES, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no'>
        </head>
        """
        let htmlEnd = "</BODY></HTML>"
        let htmlString = "\(htmlStart)\(css(colorScheme: colorScheme))\(html)\(htmlEnd)"
        webview.loadHTMLString(htmlString, baseURL: nil)
        webview.isOpaque = false
        webview.backgroundColor = UIColor.clear
        webview.scrollView.backgroundColor = UIColor.clear
        //
        return webview
    }
    
    public func updateUIView(_ uiView: WKWebView, context: Context) {}
    
    func css(colorScheme: colorScheme) -> String {
        switch colorScheme {
        case .light:
            return """
            <style type='text/css'>
                img{max-height: 100%; min-height: 100%; height:auto; max-width: 100%; width:auto;margin-bottom:5px; border-radius: \(imageRadius)px;}
            h1, h2, h3, h4, h5, h6, p, dl, ol, ul, pre, blockquote {text-align:left|right|center; line-height: \(lineHeight)%; font-family: '\(fontName(fontType: fontType))'; color: #000000 \(colorImportant == false ? "" : "!important"); }
                iframe{width:100%; height:250px;}
            a:link {color: \(linkColor.light);}
            A {text-decoration: none;}
            </style>
            <BODY>
            """
        case .dark:
            return """
            <style type='text/css'>
                img{max-height: 100%; min-height: 100%; height:auto; max-width: 100%; width:auto;margin-bottom:5px; border-radius: \(imageRadius)px;}
            h1, h2, h3, h4, h5, h6, p, dl, ol, ul, pre, blockquote {text-align:left|right|center; line-height: \(lineHeight)%; font-family: '\(fontName(fontType: fontType))'; color: #F2F2F2 \(colorImportant == false ? "" : "!important"); }
                iframe{width:100%; height:250px;}
            a:link {color: \(linkColor.dark);}
            A {text-decoration: none;}
            </style>
            <BODY>
            """
        case .automatic:
            return """
            <style type='text/css'>
            @media (prefers-color-scheme: light) {
                img{max-height: 100%; min-height: 100%; height:auto; max-width: 100%; width:auto;margin-bottom:5px; border-radius: \(imageRadius)px;}
            h1, h2, h3, h4, h5, h6, p, dl, ol, ul, pre, blockquote {text-align:left|right|center; line-height: \(lineHeight)%; font-family: '\(fontName(fontType: fontType))'; color: #000000 \(colorImportant == false ? "" : "!important"); }
                iframe{width:100%; height:250px;}
            a:link {color: \(linkColor.light);}
            A {text-decoration: none;}
            }
            @media (prefers-color-scheme: dark) {
                img{max-height: 100%; min-height: 100%; height:auto; max-width: 100%; width:auto;margin-bottom:5px; border-radius: \(imageRadius)px;}
            h1, h2, h3, h4, h5, h6, p, dl, ol, ul, pre, blockquote {text-align:left|right|center; line-height: \(lineHeight)%; font-family: '\(fontName(fontType: fontType))'; color: #F2F2F2 \(colorImportant == false ? "" : "!important"); }
                iframe{width:100%; height:250px;}
            a:link {color: \(linkColor.dark);}
            A {text-decoration: none;}
            }
            </style>
            <BODY>
            """
        }
    }
    
    func fontName(fontType: fontType) -> String {
        switch fontType {
        case .system:
            return "-apple-system"
        case .monospaced:
            return UIFont.monospacedSystemFont(ofSize: 17, weight: .regular).fontName
        case .italic:
            return UIFont.italicSystemFont(ofSize: 17).fontName
            
        default:
            return "-apple-system"
        }
    }
}
